﻿using System;
using System.Collections.Generic;
using System.Linq;

namespace Gmantis.Controls.DataGrid
{
    internal class DataGridFilterManager
    {
        // Fields
        private DataGridColumn[] _filteredColumns;

        // Events
        public event EventHandler FilterChanged;

        // Methods
        internal DataGridFilterManager(DataGridModel model)
        {
            this.Model = model;
        }

        internal void FilterBy(bool preservePreviousFilters, params DataGridColumnValue<DataGridFilterState>[] columns)
        {
            DataGridColumnValue<DataGridFilterState>[] valueArray = columns;
            if (preservePreviousFilters)
            {
                List<DataGridColumnValue<DataGridFilterState>> source = new List<DataGridColumnValue<DataGridFilterState>>();
                foreach (DataGridColumn column in this.FilteredColumns)
                {
                    source.Add(new DataGridColumnValue<DataGridFilterState>(column, column.FilterState));
                }
                DataGridColumnValue<DataGridFilterState>[] valueArray2 = columns;
                for (int i = 0; i < valueArray2.Length; i++)
                {
                    Func<DataGridColumnValue<DataGridFilterState>, bool> predicate = null;
                    DataGridColumnValue<DataGridFilterState> col = valueArray2[i];
                    if (predicate == null)
                    {
                        predicate = si => si.Column == col.Column;
                    }
                    DataGridColumnValue<DataGridFilterState> value2 = source.FirstOrDefault<DataGridColumnValue<DataGridFilterState>>(predicate);
                    if (value2 == null)
                    {
                        source.Add(col);
                    }
                    else
                    {
                        value2.Value = col.Value;
                    }
                }
                valueArray = source.ToArray();
            }
            valueArray = (from fi in valueArray
                          where fi.Value != null
                          select fi).ToArray<DataGridColumnValue<DataGridFilterState>>();
            DataGridFilterChangingEventArgs e = new DataGridFilterChangingEventArgs(valueArray);
            this.Model.DataGrid.OnFilterChanging(e);
            if (!e.Cancel)
            {
                if (!this.Model.DataGrid.IsFilteringRowsAllowed)
                {
                    throw new DataGridFilterException("Filtering rows isn't allowed.");
                }
                try
                {
                    this.Model.DataConnection.FilterDescriptions = valueArray;
                }
                catch (Exception exception)
                {
                    throw new DataGridFilterException("There was an error when filtering rows.", exception);
                }
            }
        }

        internal void InvalidateFilteredColumns()
        {
            this._filteredColumns = null;
        }

        private void OnFilterChanged()
        {
            if (this.FilterChanged != null)
            {
                this.FilterChanged(this, new EventArgs());
            }
        }

        internal void SetCurrentFilteredColumns(DataGridColumnValue<DataGridFilterState>[] filteredColumns)
        {
            List<DataGridColumnValue<DataGridFilterState>> list = new List<DataGridColumnValue<DataGridFilterState>>();
            foreach (DataGridColumn column in this.FilteredColumns)
            {
                list.Add(new DataGridColumnValue<DataGridFilterState>(column, column.FilterState));
            }
            bool flag = false;
            foreach (DataGridColumnValue<DataGridFilterState> value2 in filteredColumns)
            {
                DataGridColumn column2 = value2.Column;
                flag |= column2.FilterState != value2.Value;
                column2.FilterState = value2.Value;
            }
            DataGridColumn[] columnArray2 = this.FilteredColumns;
            for (int i = 0; i < columnArray2.Length; i++)
            {
                Func<DataGridColumnValue<DataGridFilterState>, bool> predicate = null;
                DataGridColumn column = columnArray2[i];
                if (predicate == null)
                {
                    predicate = pair => pair.Column == column;
                }
                if (filteredColumns.Where<DataGridColumnValue<DataGridFilterState>>(predicate).Count<DataGridColumnValue<DataGridFilterState>>() == 0)
                {
                    column.FilterState = null;
                    flag = true;
                }
            }
            this.InvalidateFilteredColumns();
            if (flag)
            {
                DataGridFilterChangedEventArgs e = new DataGridFilterChangedEventArgs(filteredColumns, list.ToArray());
                this.OnFilterChanged();
                this.Model.DataGrid.OnFilterChanged(e);
            }
        }

        // Properties
        public IEnumerable<FilterDescription> FilterDescriptions
        {
            get
            {
                foreach (DataGridColumn iteratorVariable0 in this.FilteredColumns)
                {
                    yield return new FilterDescription(iteratorVariable0.ActualFilterMemberPath, iteratorVariable0.FilterState);
                }
            }
        }

        internal DataGridColumn[] FilteredColumns
        {
            get
            {
                if (this._filteredColumns == null)
                {
                    this._filteredColumns = (from column in this.Model.Columns
                                             where column.FilterState != null
                                             select column).ToArray<DataGridColumn>();
                }
                return this._filteredColumns;
            }
        }

        private DataGridModel Model { get; set; }
    }
}
